<?php
declare(strict_types=1);

namespace app\common\service\sms\driver;

use app\common\service\sms\Driver;
use think\App;
use Overtrue\EasySms\EasySms;
use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;

class Overtrue extends Driver
{
    protected $config = [
        'type' => 'Overtrue',
        'handler_config' => [
            // HTTP 请求的超时时间（秒）
            'timeout' => 10,

            // 默认发送配置
            'default' => [
                // 网关调用策略，默认：顺序调用
                'strategy' => \Overtrue\EasySms\Strategies\OrderStrategy::class,

                // 默认可用的发送网关
                'gateways' => [
                    'yunpian',
                    // 'aliyun',
                ],
            ],
            // 可用的网关配置
            'gateways' => [
                'errorlog' => [
                    'file' => '', // /tmp/easy-sms.log
                ],
                'yunpian' => [
                    'api_key' => 'xxx',
                ],
                // 'aliyun' => [
                //     'access_key_id' => '',
                //     'access_key_secret' => '',
                //     'sign_name' => '',
                // ],
                //...
            ],
        ],
    ];
    protected $handler = null;

    public function __construct(App $app, array $config = [])
    {
        $this->config = array_merge($this->config, $config);

        if (empty($this->config['handler_config']['gateways']['errorlog']['file'])) {
            $this->config['handler_config']['gateways']['errorlog']['file'] = $app->getRuntimePath() . 'log/easy-sms.log';
        }

        $this->handler = new EasySms($this->config['handler_config']);
    }

    /**
     * 发送短信
     * @param string $phone 手机号码
     * @param array $message 短信内容 
     * 方式1 ['content' => '验证码：{code}，有效时间：{expire}分钟', 'template' => 'SMS_123456789', 'data' => ['code' => '123456', 'expire' => '5'], 'gateways' => ['yunpian', 'aliyun']
     * 
     * 方式2 ['content' =>  function($gateway){//参考官方手册返回}, 'template' =>  function($gateway){},'data' =>function($gateway){}, 'gateways' => ['yunpian', 'aliyun']
     * 方式2 暂不支持 不好处理日志
     * @return mixed
     */
    public function send(string $phone, array $message = [])
    {
        try {
            $sms_re = $this->handler->send(
                $phone,
                [
                    'content' => $message['content'] ?? '',
                    'template' => $message['template'] ?? '',
                    'data' => $message['data'] ?? [],
                ],
                $message['gateways'] ?? []
            );

            // 记录日志
            $this->log($this->config['name'], $phone, $message);

            return $this->ok('发送短信成功', $sms_re);
        } catch (NoGatewayAvailableException $e) {
            $err_msg = '短信发送失败:' . $e->getMessage() . ';' . json_encode($e->getExceptions(), JSON_UNESCAPED_UNICODE);

            $this->log($this->config['name'], $phone, $message, $err_msg);

            return $this->fail($err_msg);

            // NoGatewayAvailableException下 其他的异常 方法
            // $e->getResults();               // 返回所有 API 的结果，结构同上
            // $e->getExceptions();            // 返回所有调用异常列表
            // $e->getException($gateway);     // 返回指定网关名称的异常对象 $e->getException('yunpian')
            // $e->getLastException();         // 获取最后一个失败的异常对象

            // $exps = $e->getExceptions() ?? [];
            // foreach ($exps as $exp) {
            //     trace('短信发送失败' . json_encode($exp->getMessage(), JSON_UNESCAPED_UNICODE)); // 异常信息为空{}时，试这样
            // }
        } catch (\Exception $e) {
            $err_msg = '短信发送失败' . $e->getMessage();

            $this->log($this->config['name'], $phone, $message, $err_msg);

            return $this->fail($err_msg);
        }
    }
}
